package fr.mywiki.model.queries;

import java.rmi.RemoteException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import fr.mywiki.business.file.FileLite;
import fr.mywiki.model.ejbAdapter.utils.Sequencer;

/**
 * Unit test class for DatabaseFileController
 * 
 * @see http://localhost:8080/MyWiki/ServletTestRunner?suite=fr.mywiki.model.queries.DatabaseFileControllerTest&xsl=cactus-report.xsl
 */
public class DatabaseFileControllerTest extends TestCase {
	static Long oldkey;
	static Long key;
	public static final String FILE_NAME = "test.txt";
	public static final byte[] FILE_CONTENT = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

	public DatabaseFileControllerTest(String a_name) {
		super(a_name);
	}

	public static Test suite() {
		TestSuite suite = new TestSuite();
		suite.addTestSuite(DatabaseFileControllerTest.class);

		return suite;
	}

	/**
	 * Tests the simple creation of a file object in the database with no
	 * arguments (public method). The creation should be correctly done.
	 */
	public void testSimpleCreateFileObject() {
		try {
			FileLite file = DatabaseFileController.createFile();
			oldkey = file.getId();
		} catch (Exception e) {
			fail("Creation of the file object");
		}
	}
	
	/**
	 * Tests the creation of an identified file object, the identifier having
	 * already been taken for another file.
	 */
	public void testImpossibleCreateObject() {
		try {
			DatabaseFileController.createFile(oldkey);
			fail("Creation happened...");
		} catch (SQLException e) {
		}
	}

	/**
	 * Tests the creation of a file object in the database with arguments
	 * (protected method). The creation should be correctly done.
	 */
	public void testCreateFileObject() {
		try {
			key = new Long(Sequencer.getInstance(FileLite.JNDI_NAME).next());
			while (DatabaseFileController.findFileByPrimaryKey(key) != null)
				key = new Long(Sequencer.getInstance(FileLite.JNDI_NAME).next());
		} catch (Exception e1) {
			fail("Exception while trying to retrieve the key.");
		}

		assertNotNull(key);
		FileLite file = null;
		try {
			file = DatabaseFileController.createFile(key);
		} catch (SQLException e) {
			fail("SQLException while creating the file object");
		}

		assertNotNull(file);
		assertEquals(key, file.getId());

		String sql = "select id, name from file_ where id=" + key;
		ResultList result = null;
		try {
			result = DatabaseAdapter.executeSelectQuery(sql);
		} catch (SQLException e2) {
			fail("Exception while trying to reaccess the document");
		}

		Object[] res = result.getRecord(0);
		assertEquals(key, res[0]);
		assertNull(res[1]);
	}

	/**
	 * Testing the update of a file object.
	 */
	public void testUpdateFileObject() {
		FileLite file = new FileLite();
		file.setId(key);
		file.setName(FILE_NAME);
		file.setContent(FILE_CONTENT);

		try {
			DatabaseFileController.updateFile(file);
		} catch (RemoteException e) {
			fail("Exception while updating the file object");
		}

		String sql = "select id, name from file_ where id=" + key;
		ResultList result = null;
		try {
			result = DatabaseAdapter.executeSelectQuery(sql);
		} catch (SQLException e2) {
			fail("Exception while trying to reaccess the document");
		}

		Object[] res = result.getRecord(0);
		assertEquals(key, res[0]);
		assertEquals(FILE_NAME, res[1]);
	}
	
	/**
	 * Tests findAllFileObjects() method. Should return the correct number of
	 * objects, themselves having the correct type and fields.
	 */
	public void testFindAllFileObjects() {
		Collection results = null;
		try {
			results = DatabaseFileController.findAllFile();
		} catch (RemoteException e) {
			fail("Exception while computing all the file objects");
		}
		
		assertTrue(results.size() >= 2);
		boolean found1 = false;
		boolean found2 = false;
		Iterator itResults = results.iterator();
		while(itResults.hasNext()) {
			FileLite file = (FileLite)itResults.next();
			if(oldkey.equals(file.getId())) {
				assertNull(file.getName());
				assertNull(file.getContent());
				found1 = true;
			}
			if(key.equals(file.getId())) {
				assertEquals(FILE_NAME,file.getName());
				byte[] array = (byte[]) file.getContent();
				assertEquals(FILE_CONTENT.length, array.length);
				for (int i = 0; i < FILE_CONTENT.length; i++)
					assertEquals(FILE_CONTENT[0], array[0]);
				found2 = true;
			}
		}
		assertTrue(found1);
		assertTrue(found2);
	}

	/**
	 * Testing the update of an inexistant file object.
	 */
	public void testUpdateInexistantFileObject() {
		FileLite file = new FileLite();
		file.setId(new Long(-1));
		file.setName(FILE_NAME);
		file.setContent(FILE_CONTENT);

		try {
			DatabaseFileController.updateFile(file);
		} catch (RemoteException e) {
			fail("Exception while updating the file object");
		}
	}

	/** Testing the method findFileByPrimaryKey(). Is data correctly built ? */
	public void testGetExistantFileObject() {
		FileLite file = null;
		try {
			file = DatabaseFileController.findFileByPrimaryKey(key);
		} catch (RemoteException e) {
			fail("RemoteException in findFileByPrimaryKey");
		}
		assertNotNull(file);
		assertEquals(key, file.getId());
		assertEquals(FILE_NAME, file.getName());
		
		byte[] array = (byte[]) file.getContent();
		assertEquals(FILE_CONTENT.length, array.length);
		for (int i = 0; i < FILE_CONTENT.length; i++)
			assertEquals(FILE_CONTENT[0], array[0]);
	}

	/**
	 * Testing the method findFileByPrimaryKey
	 */
	public void testGetInexistantFileObject() {
		try {
			assertNull(DatabaseFileController
					.findFileByPrimaryKey(new Long(-1)));
		} catch (RemoteException e) {
			fail("RemoteException");
		}
	}
	
	/** Testing the removal of a file object. */
	public void testRemoveFileObject() {
		try {
			DatabaseFileController.removeFile(key);
		} catch (RemoteException e) {
			fail("Could not remove file object");
		}
		
		try {
			assertNull(DatabaseFileController
					.findFileByPrimaryKey(key));
		} catch (RemoteException e) {
			fail("RemoteException");
		}
	}
}